// #include "../debug-logger/log.hpp"
#include "../Logger/log.hpp"
#include <thread>
#include <chrono>
#include <algorithm>
#include <string>
using namespace LoggerSpace;
/*
测试性能文件:
如何测试?
同步日志器&异步日志器
单线程&单线程
多线程VS多线程
测试每秒钟可以输出多少条日志信息=总条数/总时间
每秒可以输出多少KB的日志信息=日志/s * 每条日志大小
*/
// 告诉我日志器名称,线程数,日志条数,每条日志的大小
void bench(const std::string &name, size_t thNums, size_t size, size_t len, bool lev)
{

    auto it = LoggerSpace::getLogger(name);
    // 记录每个线程所花费的时间
    std::vector<double> costs(thNums);
    // 记录每个线程应该打印的日志信息条数
    std::vector<size_t> nums(thNums, size / thNums);
    if (size % thNums)
        nums[0] += size % thNums;
    // 构建测试消息
    std::string str(len - 1, 'a');
    std::vector<std::thread> tids;
    for (int i = 0; i < thNums; i++)
    {
        tids.emplace_back(std::thread([&](int j) -> void
                                      {
                        int cnt=0;
                        auto start = std::chrono::high_resolution_clock::now();
                        while(cnt<nums[j])
                        {
                         it->Fatal("%s",str.c_str());
                         cnt++;
                        }
                        auto end = std::chrono::high_resolution_clock::now();
                       auto cost=std::chrono::duration_cast<std::chrono::duration<double>>(end-start);
                        costs[j]=cost.count(); },
                                      i));
    }
    for (auto &e : tids)
        e.join();

    std::cout << "\n-----------------------------------------------------" << std::endl;
    if (lev)
    {
        std::cout << "                异步日志器: "
                  << name << "\n";
    }
    else
    {
        std::cout << "                同步日志器: "
                  << name << "\n";
    }
    double Max = costs[0];
    for (int i = 0; i < thNums; i++)
        Max = std::max(costs[i], Max);
    std::cout << "[测试日志条数]:" << size << "\t"
              << "[每条日志大小]:" << len << " byte"
              << "\n"
              << "[测试线程数]:" << thNums << "\t"
              << "[测试总用时]:" << Max << "s" << std::endl;
    uint64_t tmp = size;
    std::cout << "[输出日志大小]:" << tmp * len / 1024 << "kb" << std::endl;

    for (int i = 0; i < thNums; i++)
    {
        std::cout << "线程[" << i << "]执行条数:" << nums[i] << " 耗时:" << costs[i] << "s"
                  << " 平均:" << nums[i] / costs[i] << " strip/s" << std::endl;
    }
    printf("\t总平均:%d strip/s\n", (size_t)(size / Max));
    printf("\t总平均:%lf kb/s\n", (size / Max) * len / 1024);
    std::cout << "-----------------------------------------------------" << std::endl;
}
void AsyncTest(const std::string &LoggerName, const std::string &pathName, int thnums, size_t size, size_t len)
{
    GobalLoggerBuilder go;
    go.buildFormater("%m%n");
    go.buildLevelLimits();
    go.buildLoggerName(LoggerName);
    go.buildLoggerType(Logger::LoggerType::LOGGER_ASYNC);
    //go.EableSafe(false); // 开启非安全模式，避免计算当缓冲区满了，工作线程阻塞，需要等待异步线程实际落地，需要计算实际落地的时间;非安全模式下不用
    go.buildSink<FileSink>(pathName);
    go.build();
    bench(LoggerName, thnums, size, len, true);
}
void SyncTest(const std::string &LoggerName, const std::string &pathName, int thnums, size_t size, size_t len)
{
    GobalLoggerBuilder go;
    go.buildFormater("%m%n");
    go.buildLevelLimits();
    go.buildLoggerName(LoggerName);
    go.buildLoggerType(Logger::LoggerType::LOGGER_SYNC);
    go.buildSink<FileSink>(pathName);
    go.build();
    bench(LoggerName, thnums, size, len, false);
}
// 同步日志器 单线程vs多线程
void test1()
{
    SyncTest("sync1", "./Log/sync1.log", 1, 1000000, 100);
    SyncTest("sync2", "./Log/sync2.log", 5, 1000000, 100);
}
// 异步日志器 单线程 vs 多线程
void test2()
{
    AsyncTest("async1", "./Log/async1.log", 1, 1000000, 100);
    AsyncTest("async2", "./Log/async2.log", 5, 1000000, 100);
}
// 同步日志器 vs 异步日志器 单线程
void test3()
{
    AsyncTest("async3", "./Log/async3.log", 1, 1000000, 100);
    SyncTest("sync3", "./Log/sync3.log", 1, 1000000, 100);
}
// 同步日志器 vs 异步日志器 多线程
void test4()
{
    AsyncTest("async4", "./Log/async4.log", 5, 1000000, 100);
    SyncTest("sync4", "./Log/sync4.log", 5, 1000000, 100);
}
int main()
{
    test4();
    // test1();
    // std::cout<<"**********************************"<<std::endl;
    // test2();
    return 0;
}
